<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数据库分组查询动画演示</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3b82f6',
                        secondary: '#6b7280',
                        accent: '#8b5cf6',
                        dark: '#1f2937',
                        light: '#f9fafb'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <!-- 自定义工具类 -->
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .card-gradient {
                background: linear-gradient(135deg, #ffffff 0%, #f3f4f6 100%);
            }
            .table-shadow {
                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
            }
            .transition-medium {
                transition: all 0.3s ease;
            }
            .highlight-row {
                animation: highlight 1s ease;
            }
            @keyframes highlight {
                0% { background-color: rgba(139, 92, 246, 0.2); }
                100% { background-color: transparent; }
            }
            .step-indicator {
                transition: all 0.3s ease;
            }
            .step-indicator.active {
                background-color: theme('colors.accent');
                color: white;
            }
        }
    </style>
</head>
<body class="bg-gray-50 font-inter text-dark min-h-screen">
    <!-- 页面头部 -->
    <header class="bg-white shadow-md">
        <div class="container mx-auto px-4 py-6">
            <h1 class="text-3xl font-bold text-center">
                <i class="fa fa-database text-accent mr-2"></i>
                数据库分组查询动画演示
            </h1>
            <p class="text-center text-secondary mt-2">直观展示分组查询的执行过程和原理</p>
        </div>
    </header>

    <!-- 主内容区域 -->
    <main class="container mx-auto px-4 py-8">
        <!-- 步骤指示器 -->
        <div class="mb-8 flex justify-center">
            <div class="flex items-center space-x-2 md:space-x-4">
                <div id="step1" class="step-indicator active px-4 py-2 rounded-full text-sm font-medium">
                    <i class="fa fa-sort mr-1"></i> 按字段排序
                </div>
                <div class="hidden md:block text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step2" class="step-indicator px-4 py-2 rounded-full text-sm font-medium bg-gray-200">
                    <i class="fa fa-object-group mr-1"></i> 分组处理
                </div>
                <div class="hidden md:block text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step3" class="step-indicator px-4 py-2 rounded-full text-sm font-medium bg-gray-200">
                    <i class="fa fa-calculator mr-1"></i> 聚合计算
                </div>
                <div class="hidden md:block text-secondary">
                    <i class="fa fa-long-arrow-right"></i>
                </div>
                <div id="step4" class="step-indicator px-4 py-2 rounded-full text-sm font-medium bg-gray-200">
                    <i class="fa fa-table mr-1"></i> 展示结果
                </div>
            </div>
        </div>

        <!-- 控制面板 -->
        <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
            <!-- 查询参数设置 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-sliders text-primary mr-2"></i>查询参数设置
                </h3>
                
                <div class="space-y-4">
                    <div>
                        <label class="block text-sm font-medium text-secondary mb-1">选择分组字段</label>
                        <select id="groupByField" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary">
                            <option value="department">部门 (department)</option>
                            <option value="position">职位 (position)</option>
                            <option value="gender">性别 (gender)</option>
                        </select>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-secondary mb-1">选择聚合函数</label>
                        <select id="aggregateFunction" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary">
                            <option value="COUNT(*)">COUNT(*) - 记录数</option>
                            <option value="AVG(salary)">AVG(salary) - 平均工资</option>
                            <option value="SUM(salary)">SUM(salary) - 工资总和</option>
                            <option value="MAX(salary)">MAX(salary) - 最高工资</option>
                            <option value="MIN(salary)">MIN(salary) - 最低工资</option>
                        </select>
                    </div>
                    
                    <div class="pt-2">
                        <button id="executeBtn" class="w-full bg-accent hover:bg-accent/90 text-white py-3 px-6 rounded-lg transition-medium flex items-center justify-center">
                            <i class="fa fa-play-circle mr-2"></i>
                            开始演示
                        </button>
                    </div>
                    
                    <div class="pt-2">
                        <button id="resetBtn" class="w-full bg-gray-200 hover:bg-gray-300 text-gray-700 py-3 px-6 rounded-lg transition-medium flex items-center justify-center">
                            <i class="fa fa-refresh mr-2"></i>
                            重置演示
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- SQL查询语句展示 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-code text-primary mr-2"></i>SQL查询语句
                </h3>
                
                <div class="bg-gray-900 text-gray-100 p-4 rounded-lg font-mono text-sm overflow-x-auto">
                    <pre id="sqlQuery">SELECT department, COUNT(*) FROM employees GROUP BY department;</pre>
                </div>
                
                <div class="mt-4 p-4 bg-primary/10 rounded-lg">
                    <h4 class="font-semibold text-dark mb-2">分组查询说明</h4>
                    <ul class="list-disc list-inside text-gray-700 space-y-1 text-sm">
                        <li>1. 首先按分组字段对数据进行排序</li>
                        <li>2. 根据排序后的结果将相同值的记录归类到同一组</li>
                        <li>3. 对每个分组应用聚合函数计算统计值</li>
                        <li>4. 最终返回每个分组的结果记录</li>
                    </ul>
                </div>
            </div>
        </div>
        
        <!-- 演示区域 -->
        <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
            <!-- 原始数据和排序过程 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-list-alt text-primary mr-2"></i>
                    <span id="sourceTableTitle">原始数据</span>
                </h3>
                
                <div class="overflow-x-auto">
                    <table id="sourceTable" class="min-w-full bg-white rounded-lg overflow-hidden">
                        <thead class="bg-primary text-white">
                            <tr>
                                <th class="px-4 py-3 text-left">ID</th>
                                <th class="px-4 py-3 text-left">姓名</th>
                                <th class="px-4 py-3 text-left">部门</th>
                                <th class="px-4 py-3 text-left">职位</th>
                                <th class="px-4 py-3 text-left">性别</th>
                                <th class="px-4 py-3 text-left">工资</th>
                            </tr>
                        </thead>
                        <tbody id="sourceTableBody">
                            <!-- 数据将通过JavaScript动态生成 -->
                        </tbody>
                    </table>
                </div>
            </div>
            
            <!-- 分组结果 -->
            <div class="card-gradient rounded-xl p-6 table-shadow">
                <h3 class="text-xl font-bold text-dark mb-4 flex items-center">
                    <i class="fa fa-table text-accent mr-2"></i>
                    分组查询结果
                </h3>
                
                <div id="processingIndicator" class="hidden p-6 text-center">
                    <div class="inline-block animate-spin rounded-full h-8 w-8 border-4 border-gray-200 border-t-accent mb-2"></div>
                    <p class="text-gray-600" id="processingText">正在按部门排序...</p>
                </div>
                
                <div class="overflow-x-auto">
                    <table id="resultTable" class="min-w-full bg-white rounded-lg overflow-hidden">
                        <thead id="resultTableHead" class="bg-accent text-white">
                            <tr>
                                <th class="px-4 py-3 text-left">部门</th>
                                <th class="px-4 py-3 text-left">员工数量</th>
                            </tr>
                        </thead>
                        <tbody id="resultTableBody">
                            <!-- 结果将通过JavaScript动态生成 -->
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </main>

    <!-- 页脚 -->
    <footer class="bg-white py-6 mt-12 border-t border-gray-200">
        <div class="container mx-auto px-4 text-center text-secondary">
            <p>数据库分组查询动画演示 © 2024</p>
        </div>
    </footer>

    <!-- JavaScript -->
    <script>
        // 定义原始员工数据
        const employees = [
            { id: 1, name: '张三', department: '技术部', position: '软件工程师', gender: '男', salary: 15000 },
            { id: 2, name: '李四', department: '技术部', position: '产品经理', gender: '女', salary: 18000 },
            { id: 3, name: '王五', department: '市场部', position: '市场专员', gender: '男', salary: 12000 },
            { id: 4, name: '赵六', department: '人力资源部', position: 'HR', gender: '女', salary: 10000 },
            { id: 5, name: '钱七', department: '财务部', position: '会计', gender: '女', salary: 13000 },
            { id: 6, name: '孙八', department: '技术部', position: 'UI设计师', gender: '男', salary: 14000 },
            { id: 7, name: '周九', department: '市场部', position: '市场经理', gender: '男', salary: 19000 },
            { id: 8, name: '吴十', department: '财务部', position: '财务经理', gender: '女', salary: 20000 }
        ];

        // 全局状态变量
        let currentStep = 0;
        let sortedData = [];
        let groupedData = [];
        let animationSteps = [];
        let animationIndex = 0;
        let selectedGroupField = 'department';
        let selectedAggregateFunc = 'COUNT(*)';

        // DOM元素
        const sourceTableBody = document.getElementById('sourceTableBody');
        const resultTableBody = document.getElementById('resultTableBody');
        const sqlQuery = document.getElementById('sqlQuery');
        const groupByField = document.getElementById('groupByField');
        const aggregateFunction = document.getElementById('aggregateFunction');
        const executeBtn = document.getElementById('executeBtn');
        const resetBtn = document.getElementById('resetBtn');
        const sourceTableTitle = document.getElementById('sourceTableTitle');
        const processingIndicator = document.getElementById('processingIndicator');
        const processingText = document.getElementById('processingText');
        const resultTableHead = document.getElementById('resultTableHead');
        
        // 步骤指示器元素
        const step1 = document.getElementById('step1');
        const step2 = document.getElementById('step2');
        const step3 = document.getElementById('step3');
        const step4 = document.getElementById('step4');

        // 动画延迟常量
        const ANIMATION_DELAY = 800;

        // 初始化页面
        function initializePage() {
            renderSourceTable(employees);
            updateSqlQuery();
            updateResultTableHeader();
            resetSteps();
        }

        // 渲染原始数据表
        function renderSourceTable(data) {
            sourceTableBody.innerHTML = '';
            
            data.forEach(employee => {
                const row = document.createElement('tr');
                row.className = 'border-b transition-medium hover:bg-gray-50';
                
                // 高亮分组字段列
                const deptClass = employee.department === selectedGroupField ? 'bg-yellow-100 font-bold' : '';
                const posClass = employee.position === selectedGroupField ? 'bg-yellow-100 font-bold' : '';
                const genClass = employee.gender === selectedGroupField ? 'bg-yellow-100 font-bold' : '';
                
                row.innerHTML = `
                    <td class="px-4 py-3">${employee.id}</td>
                    <td class="px-4 py-3">${employee.name}</td>
                    <td class="px-4 py-3 ${selectedGroupField === 'department' ? 'bg-yellow-100 font-bold' : ''}">${employee.department}</td>
                    <td class="px-4 py-3 ${selectedGroupField === 'position' ? 'bg-yellow-100 font-bold' : ''}">${employee.position}</td>
                    <td class="px-4 py-3 ${selectedGroupField === 'gender' ? 'bg-yellow-100 font-bold' : ''}">${employee.gender}</td>
                    <td class="px-4 py-3">${employee.salary.toLocaleString()}</td>
                `;
                
                sourceTableBody.appendChild(row);
            });
        }

        // 更新SQL查询语句
        function updateSqlQuery() {
            const groupField = groupByField.value === 'department' ? 'department' : 
                              groupByField.value === 'position' ? 'position' : 'gender';
            
            const funcText = aggregateFunction.options[aggregateFunction.selectedIndex].text;
            const funcName = funcText.split(' - ')[1];
            
            sqlQuery.textContent = `SELECT ${groupField}, ${aggregateFunction.value} FROM employees GROUP BY ${groupField};`;
        }

        // 更新结果表头
        function updateResultTableHeader() {
            const groupFieldLabel = groupByField.options[groupByField.selectedIndex].text.split(' (')[0];
            const funcText = aggregateFunction.options[aggregateFunction.selectedIndex].text.split(' - ')[1];
            
            resultTableHead.innerHTML = `
                <tr>
                    <th class="px-4 py-3 text-left">${groupFieldLabel}</th>
                    <th class="px-4 py-3 text-left">${funcText}</th>
                </tr>
            `;
        }

        // 重置步骤指示器
        function resetSteps() {
            currentStep = 0;
            animationIndex = 0;
            
            // 重置步骤样式
            step1.classList.add('active');
            step1.classList.remove('bg-gray-200');
            
            [step2, step3, step4].forEach(step => {
                step.classList.remove('active');
                step.classList.add('bg-gray-200');
            });
            
            // 重置表标题
            sourceTableTitle.textContent = '原始数据';
            
            // 隐藏处理指示器
            processingIndicator.classList.add('hidden');
            
            // 清空结果表
            resultTableBody.innerHTML = '';
        }

        // 开始演示动画
        function startAnimation() {
            // 获取用户选择的参数
            selectedGroupField = groupByField.value;
            selectedAggregateFunc = aggregateFunction.value;
            
            // 更新界面
            updateSqlQuery();
            updateResultTableHeader();
            resetSteps();
            
            // 准备排序数据
            sortedData = [...employees].sort((a, b) => {
                if (a[selectedGroupField] < b[selectedGroupField]) return -1;
                if (a[selectedGroupField] > b[selectedGroupField]) return 1;
                return 0;
            });
            
            // 准备分组数据
            groupedData = {};
            sortedData.forEach(employee => {
                const key = employee[selectedGroupField];
                if (!groupedData[key]) {
                    groupedData[key] = [];
                }
                groupedData[key].push(employee);
            });
            
            // 准备动画步骤
            prepareAnimationSteps();
            
            // 禁用按钮
            executeBtn.disabled = true;
            executeBtn.classList.add('opacity-50', 'cursor-not-allowed');
            
            // 开始执行动画
            executeAnimation();
        }

        // 准备动画步骤
        function prepareAnimationSteps() {
            animationSteps = [];
            
            // 步骤1: 排序动画
            animationSteps.push({
                type: 'sorting',
                execute: () => {
                    executeStep1();
                }
            });
            
            // 步骤2: 分组动画
            animationSteps.push({
                type: 'grouping',
                execute: () => {
                    executeStep2();
                }
            });
            
            // 步骤3: 计算动画
            animationSteps.push({
                type: 'calculating',
                execute: () => {
                    executeStep3();
                }
            });
            
            // 步骤4: 显示结果
            animationSteps.push({
                type: 'result',
                execute: () => {
                    executeStep4();
                }
            });
        }

        // 执行动画
        function executeAnimation() {
            if (animationIndex < animationSteps.length) {
                const step = animationSteps[animationIndex];
                step.execute();
                animationIndex++;
            } else {
                // 动画完成，重新启用按钮
                setTimeout(() => {
                    executeBtn.disabled = false;
                    executeBtn.classList.remove('opacity-50', 'cursor-not-allowed');
                }, 500);
            }
        }

        // 执行步骤1: 排序
        function executeStep1() {
            // 显示处理指示器
            processingIndicator.classList.remove('hidden');
            processingText.textContent = `正在按${getGroupFieldLabel()}排序...`;
            
            // 更新步骤指示器
            step1.classList.remove('bg-gray-200');
            step1.classList.add('active');
            
            // 延迟后显示排序结果
            setTimeout(() => {
                processingIndicator.classList.add('hidden');
                sourceTableTitle.textContent = `排序后数据 (按${getGroupFieldLabel()}升序)`;
                renderSourceTable(sortedData);
                
                // 高亮排序后的分组边界
                highlightGroupBoundaries();
                
                // 继续下一步
                setTimeout(executeAnimation, ANIMATION_DELAY);
            }, 1500);
        }

        // 执行步骤2: 分组
        function executeStep2() {
            // 更新步骤指示器
            step2.classList.remove('bg-gray-200');
            step2.classList.add('active');
            
            // 显示分组处理指示器
            processingIndicator.classList.remove('hidden');
            processingText.textContent = `正在按${getGroupFieldLabel()}分组...`;
            
            // 延迟后显示分组标记
            setTimeout(() => {
                processingIndicator.classList.add('hidden');
                sourceTableTitle.textContent = `分组后数据 (按${getGroupFieldLabel()})`;
                
                // 重新渲染表格并添加分组标记
                renderSourceTableWithGroups();
                
                // 继续下一步
                setTimeout(executeAnimation, ANIMATION_DELAY);
            }, 1500);
        }

        // 执行步骤3: 计算
        function executeStep3() {
            // 更新步骤指示器
            step3.classList.remove('bg-gray-200');
            step3.classList.add('active');
            
            // 显示计算指示器
            processingIndicator.classList.remove('hidden');
            processingText.textContent = `正在计算每个分组的${getAggregateLabel()}...`;
            
            // 延迟后开始计算动画
            setTimeout(() => {
                processingIndicator.classList.add('hidden');
                
                // 逐个显示计算过程
                let delay = 0;
                Object.keys(groupedData).forEach((key, index) => {
                    setTimeout(() => {
                        showCalculationStep(key, index);
                    }, delay);
                    delay += ANIMATION_DELAY;
                });
                
                // 所有计算完成后继续下一步
                setTimeout(executeAnimation, delay + 500);
            }, 1000);
        }

        // 执行步骤4: 显示最终结果
        function executeStep4() {
            // 更新步骤指示器
            step4.classList.remove('bg-gray-200');
            step4.classList.add('active');
            
            // 清空结果表
            resultTableBody.innerHTML = '';
            
            // 显示最终结果
            const keys = Object.keys(groupedData);
            keys.forEach((key, index) => {
                setTimeout(() => {
                    addResultRow(key);
                }, index * ANIMATION_DELAY);
            });
        }

        // 获取分组字段的中文标签
        function getGroupFieldLabel() {
            const option = groupByField.options[groupByField.selectedIndex];
            return option ? option.text.split(' (')[0] : '';
        }

        // 获取聚合函数的中文标签
        function getAggregateLabel() {
            const option = aggregateFunction.options[aggregateFunction.selectedIndex];
            return option ? option.text.split(' - ')[1] : '';
        }

        // 高亮分组边界
        function highlightGroupBoundaries() {
            const rows = sourceTableBody.querySelectorAll('tr');
            let currentGroup = null;
            
            rows.forEach((row, index) => {
                const employee = sortedData[index];
                const groupValue = employee[selectedGroupField];
                
                if (groupValue !== currentGroup) {
                    // 新分组开始
                    currentGroup = groupValue;
                    row.classList.add('border-t-2', 'border-accent');
                }
            });
        }

        // 渲染带有分组标记的表格
        function renderSourceTableWithGroups() {
            sourceTableBody.innerHTML = '';
            
            let currentGroup = null;
            let groupCount = 0;
            
            sortedData.forEach((employee, index) => {
                const groupValue = employee[selectedGroupField];
                
                // 新分组开始
                if (groupValue !== currentGroup) {
                    currentGroup = groupValue;
                    groupCount++;
                    
                    // 添加分组标题行
                    const groupHeader = document.createElement('tr');
                    groupHeader.className = 'bg-accent/10 font-semibold';
                    groupHeader.innerHTML = `
                        <td colspan="6" class="px-4 py-2">
                            <span class="inline-block px-2 py-1 bg-accent text-white rounded text-xs mr-2">组 ${groupCount}</span>
                            ${getGroupFieldLabel()}: ${groupValue} (共 ${groupedData[groupValue].length} 条记录)
                        </td>
                    `;
                    sourceTableBody.appendChild(groupHeader);
                }
                
                // 添加数据行
                const row = document.createElement('tr');
                row.className = 'border-b transition-medium hover:bg-gray-50';
                
                // 高亮分组字段
                const deptClass = selectedGroupField === 'department' ? 'bg-yellow-100 font-bold' : '';
                const posClass = selectedGroupField === 'position' ? 'bg-yellow-100 font-bold' : '';
                const genClass = selectedGroupField === 'gender' ? 'bg-yellow-100 font-bold' : '';
                
                row.innerHTML = `
                    <td class="px-4 py-3">${employee.id}</td>
                    <td class="px-4 py-3">${employee.name}</td>
                    <td class="px-4 py-3 ${deptClass}">${employee.department}</td>
                    <td class="px-4 py-3 ${posClass}">${employee.position}</td>
                    <td class="px-4 py-3 ${genClass}">${employee.gender}</td>
                    <td class="px-4 py-3">${employee.salary.toLocaleString()}</td>
                `;
                
                sourceTableBody.appendChild(row);
            });
        }

        // 显示计算步骤
        function showCalculationStep(groupKey, groupIndex) {
            // 找到对应的分组行
            const rows = sourceTableBody.querySelectorAll('tr');
            let groupRowIndex = -1;
            
            rows.forEach((row, index) => {
                if (row.textContent.includes(`组 ${groupIndex + 1}`)) {
                    groupRowIndex = index;
                }
            });
            
            // 高亮分组中的所有行
            if (groupRowIndex !== -1) {
                let currentIndex = groupRowIndex + 1;
                const groupSize = groupedData[groupKey].length;
                
                // 为分组行添加计算中标记
                const groupRow = rows[groupRowIndex];
                groupRow.innerHTML = `
                    <td colspan="6" class="px-4 py-2">
                        <span class="inline-block px-2 py-1 bg-accent text-white rounded text-xs mr-2">组 ${groupIndex + 1}</span>
                        ${getGroupFieldLabel()}: ${groupKey} (正在计算...)
                        <span class="inline-block ml-2 animate-pulse bg-yellow-400 text-dark px-2 py-0.5 rounded text-xs">计算中</span>
                    </td>
                `;
                
                // 计算并显示结果
                setTimeout(() => {
                    // 更新分组标题显示计算结果
                    const result = calculateAggregate(groupedData[groupKey]);
                    groupRow.innerHTML = `
                        <td colspan="6" class="px-4 py-2">
                            <span class="inline-block px-2 py-1 bg-green-500 text-white rounded text-xs mr-2">组 ${groupIndex + 1}</span>
                            ${getGroupFieldLabel()}: ${groupKey} (${getAggregateLabel()}: ${formatResult(result)})
                            <span class="inline-block ml-2 bg-green-100 text-green-800 px-2 py-0.5 rounded text-xs">计算完成</span>
                        </td>
                    `;
                }, 800);
            }
        }

        // 计算聚合函数值
        function calculateAggregate(group) {
            switch (selectedAggregateFunc) {
                case 'COUNT(*)':
                    return group.length;
                case 'AVG(salary)':
                    return group.reduce((sum, emp) => sum + emp.salary, 0) / group.length;
                case 'SUM(salary)':
                    return group.reduce((sum, emp) => sum + emp.salary, 0);
                case 'MAX(salary)':
                    return Math.max(...group.map(emp => emp.salary));
                case 'MIN(salary)':
                    return Math.min(...group.map(emp => emp.salary));
                default:
                    return group.length;
            }
        }

        // 格式化计算结果
        function formatResult(result) {
            if (typeof result === 'number') {
                // 对于平均值，保留2位小数
                if (selectedAggregateFunc === 'AVG(salary)') {
                    return result.toFixed(2).toLocaleString();
                }
                // 其他数值结果
                return Math.round(result).toLocaleString();
            }
            return result;
        }

        // 添加结果行
        function addResultRow(groupKey) {
            const result = calculateAggregate(groupedData[groupKey]);
            
            const row = document.createElement('tr');
            row.className = 'border-b transition-medium hover:bg-gray-50';
            row.style.opacity = '0';
            row.style.transform = 'translateY(10px)';
            
            row.innerHTML = `
                <td class="px-4 py-3 font-medium">${groupKey}</td>
                <td class="px-4 py-3">${formatResult(result)}</td>
            `;
            
            resultTableBody.appendChild(row);
            
            // 淡入动画
            setTimeout(() => {
                row.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
                row.style.opacity = '1';
                row.style.transform = 'translateY(0)';
            }, 10);
        }

        // 事件监听器
        groupByField.addEventListener('change', () => {
            selectedGroupField = groupByField.value;
            updateSqlQuery();
            updateResultTableHeader();
            renderSourceTable(employees);
        });

        aggregateFunction.addEventListener('change', () => {
            selectedAggregateFunc = aggregateFunction.value;
            updateSqlQuery();
            updateResultTableHeader();
        });

        executeBtn.addEventListener('click', startAnimation);

        resetBtn.addEventListener('click', () => {
            initializePage();
            executeBtn.disabled = false;
            executeBtn.classList.remove('opacity-50', 'cursor-not-allowed');
        });

        // 页面加载完成后初始化
        window.addEventListener('DOMContentLoaded', initializePage);
    </script>
</body>
</html>